home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / libs / logwrite.1 / logwrite / logwrites-1.1 / intercepts.c < prev    next >
C/C++ Source or Header  |  1996-05-29  |  6KB  |  252 lines

  1. /* intercepts.c: This file is currently the only source file for
  2.    the logwrites filter library.
  3.  
  4.    Written by Adam J. Richter
  5.    Copyright 1996 Yggdrasil Computing, Inc.
  6.  
  7.    Logwrites and its documentation, including this file, may be freely
  8.    copied under the terms and conditions of version 2 of the GNU General
  9.    Public License, as published by the Free Software Foundation
  10.    (Cambridge, Massachusetts, United States of America).
  11.  
  12. */
  13.  
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <sys/param.h>
  17. #include <fcntl.h>
  18. #include <stdarg.h>
  19. #include <unistd.h>
  20. #include <stdlib.h>
  21. #include <syscall.h>
  22. #include <stdio.h>
  23.  
  24. static int initialized = 0;
  25. static int recursive = 0;
  26.  
  27. #define PREFIX "write "
  28.  
  29. static char cwd[MAXPATHLEN + 1] = PREFIX;
  30. static char *install_log = NULL;
  31. static char *do_backups = NULL;
  32.  
  33. static void
  34. initialize (void) {
  35.   int len;
  36.  
  37.   if (initialized) return;
  38.  
  39.   if (getcwd(cwd,sizeof(cwd)) == NULL) {
  40.     strcpy (cwd, "?");
  41.     /* fail silently */
  42.   }
  43.   install_log = getenv ("INSTALL_LOG");
  44.   do_backups = getenv ("DO_BACKUPS");
  45.   initialized = 1;
  46. }
  47.  
  48. static void
  49. log_event( char *format, ... ) {
  50.   va_list arg_ptr;
  51.   FILE *log_file;
  52.  
  53.   if (!initialized) initialize();
  54.   if (recursive || !install_log) return;
  55.   recursive = 1;
  56.   if ((log_file = fopen (install_log, "a")) == NULL) {
  57.     recursive = 0;
  58.     return;
  59.   }
  60.  
  61.   va_start(arg_ptr,format);
  62.   vfprintf (log_file, format, arg_ptr);
  63.   va_end(arg_ptr);
  64.  
  65.   fclose(log_file);
  66.   recursive = 0;
  67. }
  68.  
  69. static int
  70. gen_backup_filename (const char *filename, char *backup_filename /* OUT */) {
  71.   struct stat statbuf;
  72.   int i;
  73.   char *ptr;
  74.   sprintf (backup_filename, "%s.old", filename);
  75.   if (lstat (backup_filename, &statbuf) < 0) return;
  76.   ptr = backup_filename + strlen(backup_filename);
  77.   *(ptr++) = '.';
  78.   for (i = 1;i != 0;i++) {
  79.     sprintf (ptr, "%d", i);
  80.     if (lstat (backup_filename, &statbuf) < 0) return 1;
  81.   }
  82.   backup_filename[0] = '\0';
  83.   return 0;
  84. }
  85.  
  86.  
  87. static int
  88. backup_file (const char *filename, char *backup_filename,
  89.          int regular_file_only) {
  90.   struct stat statbuf;
  91.  
  92.   if (!initialized) initialize();
  93.   if (!do_backups) return 0;
  94.   if (recursive) return 0;
  95.   if (lstat (filename, &statbuf) >= 0 &&
  96.       (S_ISREG(statbuf.st_mode) || !regular_file_only) &&
  97.       gen_backup_filename(filename, backup_filename)) {
  98.     syscall(SYS_rename, filename, backup_filename);
  99.     return 1;
  100.   }
  101.   return 0;
  102. }
  103.  
  104.  
  105. int
  106. link (const char *oldpath, const char *newpath) {
  107.   int result;
  108.  
  109.   if ((result = syscall(SYS_link, oldpath, newpath)) >= 0) {
  110.     log_event("link %s %s %s\n", cwd, oldpath, newpath);
  111.   }
  112.   return result;
  113. }
  114.  
  115. int
  116. rename (const char *oldpath, const char *newpath) {
  117.   int result;
  118.   int backed_up;
  119.   char backup_filename[MAXPATHLEN+1];
  120.  
  121.   backed_up = backup_file(newpath, backup_filename, 0);
  122.   if ((result = syscall(SYS_rename, oldpath, newpath)) >= 0) {
  123.     if (backed_up) {
  124.       log_event("backup %s %s %s\n", cwd, newpath, backup_filename);
  125.     }
  126.     log_event("rename %s %s %s\n", cwd, oldpath, newpath);
  127.   } else {
  128.     if (backed_up) {
  129.       syscall(SYS_rename, backup_filename, newpath);
  130.     }
  131.   }
  132.   return result;
  133. }
  134.  
  135. int
  136. symlink (const char *oldpath, const char *newpath) {
  137.   int result;
  138.  
  139.   if ((result = syscall(SYS_symlink, oldpath, newpath)) >= 0) {
  140.     log_event("symlink %s %s %s\n", cwd, oldpath, newpath);
  141.   }
  142.   return result;
  143. }
  144.  
  145. int
  146. unlink (const char *filename) {
  147.   int result;
  148.   char backup_filename[MAXPATHLEN+1];
  149.   int backed_up;
  150.  
  151.   backed_up = backup_file(filename, backup_filename, 0);
  152.   if ((result = syscall(SYS_unlink, filename)) >= 0) {
  153.     if (backed_up) {
  154.       log_event("backup %s %s %s\n", cwd, filename, backup_filename);
  155.     }
  156.     log_event("unlink %s %s\n", cwd, filename);
  157.   } else {
  158.     if (backed_up) {
  159.       syscall(SYS_rename, backup_filename, filename);
  160.     }
  161.   }
  162.   return result;
  163. }
  164.  
  165. int
  166. truncate (const char *filename, size_t length) {
  167.   int result;
  168.   char backup_filename[MAXPATHLEN+1];
  169.   int backed_up;
  170.  
  171.   if (length == 0) {
  172.     backed_up = backup_file(filename, backup_filename, 0);
  173.   } else {
  174.     backed_up = 0;
  175.   }
  176.   if ((result = syscall(SYS_unlink, filename)) >= 0) {
  177.     if (backed_up) {
  178.       log_event("backup %s %s %s\n", cwd, filename, backup_filename);
  179.     }
  180.     if (length == 0) {
  181.       log_event("truncate %s %s %d\n", cwd, filename, length);
  182.     }
  183.   } else {
  184.     if (backed_up) {
  185.       syscall(SYS_rename, backup_filename, filename);
  186.     }
  187.   }
  188.   return result;
  189. }
  190.  
  191. int
  192. prev_mknod (const char *filename, mode_t mode, dev_t dev) {
  193.   int result;
  194.  
  195.   if ((result = syscall(SYS_prev_mknod, mode, dev)) >= 0) {
  196.     log_event("mknod %s %s 0%o 0x%x\n", cwd, filename, mode, dev);
  197.   }
  198.   return result;
  199. }
  200.  
  201. int
  202. mkdir (const char *pathname, mode_t mode) {
  203.   int result;
  204.  
  205.   if ((result = syscall(SYS_mkdir, pathname, mode)) >= 0) {
  206.     log_event("mkdir %s %s 0%o\n", cwd, pathname, mode);
  207.   }
  208.   return result;
  209. }
  210.  
  211. /* XXX: Also intercept rmdir? */
  212.  
  213. int
  214. open( const char *filename, int flags, ... ) {
  215.   int result;
  216.   mode_t mode;
  217.   va_list arg_ptr;
  218.   char backup_filename[MAXPATHLEN+1];
  219.   int backed_up;
  220.   int record_event;
  221.  
  222.   va_start(arg_ptr,flags);
  223.   mode = va_arg(arg_ptr, mode_t);
  224.   va_end(arg_ptr);
  225.   
  226.   /* Only log write-only opens that will create the file if it doesn't
  227.      exist.  Otherwise, it is probably not an installation.  */
  228.   if ((flags & O_ACCMODE) == O_WRONLY && (flags & O_CREAT) &&
  229.       (flags & O_TRUNC)) {
  230.  
  231.     backed_up = backup_file(filename, backup_filename, 1);
  232.     record_event = 1;
  233.   } else {
  234.     backed_up = 0;
  235.     record_event = 0;
  236.   }
  237.  
  238.   result = syscall(SYS_open, filename, flags, mode);
  239.  
  240.   if (backed_up) {
  241.     if (result < 0) {
  242.       syscall(SYS_rename, backup_filename, filename);
  243.     } else {
  244.       log_event("backup %s %s %s\n", cwd, filename, backup_filename);
  245.     }
  246.   }
  247.   if (record_event) {
  248.     log_event("write %s %s 0x%x 0%o\n", cwd, filename, flags, mode);
  249.   }
  250.   return result;
  251. }
  252.